home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / newsgrp / group92c.txt / 000115_icon-group-sender _Thu Dec 17 18:35:34 1992.msg < prev    next >
Internet Message Format  |  1993-01-04  |  26KB

  1. Received: from owl.cs.arizona.edu by cheltenham.cs.arizona.edu; Sun, 20 Dec 1992 18:02:39 MST
  2. Received: by owl.cs.arizona.edu; Sun, 20 Dec 1992 18:02:36 MST
  3. Date: 17 Dec 92 18:35:34 GMT
  4. From: yuma!wendt@purdue.edu  (alan l wendt)
  5. Organization: Colorado State University, Computer Science Department
  6. Subject: Very small program development environment for Icon
  7. Message-Id: <Dec17.183534.48493@yuma.ACNS.ColoState.EDU>
  8. Sender: icon-group-request@cs.arizona.edu
  9. To: icon-group@cs.arizona.edu
  10. Status: R
  11. Errors-To: icon-group-errors@cs.arizona.edu
  12.  
  13.  
  14.  
  15. Aplogies for posting C source to this Icon group.  This is a modified
  16. version of mcc, which allows you to fix syntax  errors quickly in
  17. Icon programs.  It runs icont and stores the error output.  It then pops
  18. you back into an editor positioned at the first syntax error.
  19.  
  20. In order to use it with icont, you must define the following
  21. environment variables:
  22.  
  23. COMPILER=icont
  24. ERRORPATTERN='File %f; Line %l # %m'
  25.  
  26. Then just "mcc foo.icn" will put you into a icont-edit loop
  27. until you abort out.
  28.  
  29. Alan Wendt
  30.  
  31. --------------------------------------------------------------------------------
  32. # to unbundle, sh this file
  33. echo unbundling Makefile 1>&2
  34. cat >Makefile <<'AlBeRtEiNsTeIn'
  35. #  If you're on 4.2 or earlier, use the first line; else the second.
  36. CFLAGS= -g  -DBSD
  37. #CFLAGS=-O
  38.  
  39. mcc:    mcc.o regex.o
  40.     cc $(CFLAGS) -o mcc mcc.o regex.o
  41.  
  42. all:    mcc mcc.1
  43.  
  44. install:    all
  45.     @echo copy mcc and mcc.1 to the appropriate directories.
  46. AlBeRtEiNsTeIn
  47. echo unbundling mcc.c 1>&2
  48. cat >mcc.c <<'AlBeRtEiNsTeIn'
  49. /*  Program: mcc
  50.  *  By:      Brent Callaghan
  51.  *  Date:    July 1984
  52.  *
  53.  *  Function: Runs the C compiler, passing all command line 
  54.  *        arguments. If the compiler returns a non-zero
  55.  *        result, the syntax errors are merged with the
  56.  *        source and the user's editor is invoked. The
  57.  *        cursor is placed on the first line in error.
  58.  *        Exit from the editor re-invokes the C compiler.
  59.  *        This loop continues until the C compiler exits
  60.  *        to the linker, the source file is not changed,
  61.  *        or the user kills mcc with a keyboard interrupt
  62.  *        after exiting the editor.
  63.  *
  64.  *        Environment variables EDITOR and COMPILER may
  65.  *        be used to set an alternative editor or compiler.
  66.  *
  67.  *              ~~~  PUBLIC DOMAIN  ~~~
  68.  *        
  69.  *       This program may be freely used and distributed
  70.  *       but I would rather you did not sell it.
  71.  *
  72.  ************************************************************
  73.  */
  74.  
  75.  /* bugs: 1. only edits the first source file with errors.        */
  76.  /*       2. copies the temporary back onto the original even if    */
  77.  /*          the original is newer                    */
  78.  
  79. #if 0
  80. Mcc (Merge C Compiler) behaves just like a C for an error free
  81. compile.  However, if the compiler finds syntax errors, it merges the
  82. error messages with the source and invokes your editor (default is vi)
  83. on the merged file.  On exiting the editor it strips the merged
  84. messages and if the source file was modified it re-runs the compiler
  85. for another try.
  86.  
  87. This posting contains a shell script and a C program with identical
  88. functionality.  The C program is noticeably faster.
  89.  
  90. Made in New Zealand -->  Brent Callaghan  @ Sun Microsystems
  91.              uucp: sun!bcallaghan
  92.              phone: (415) 691 6188
  93. #endif
  94.  
  95. #include <stdio.h>
  96. #include <ctype.h>
  97. #include <signal.h>
  98. #include <sys/types.h>
  99. #include <sys/stat.h>
  100.  
  101. #ifdef BSD
  102. #include <strings.h>
  103. #define strchr  index
  104. #define strrchr rindex
  105. #else
  106. #include <string.h>
  107. #endif
  108.  
  109. extern char * getenv();
  110. static char *errname  = "/tmp/errXXXXXX";
  111. static char mergename[128];
  112. static char *srcname;
  113. static char *editor, *edname, *compiler;
  114. static int pid, viedit, firsterr;
  115. static int chksum1, chksum2;
  116. static int    filevar, linevar, msgvar;
  117. extern char *re_comp();
  118. static char    errpat[1024], errpato[1024];
  119. static char    *errdfa;
  120. extern char    *braslist[], *braelist[];
  121.  
  122. /*
  123.  * Form 16 bit checksum of source line
  124.  */
  125. int 
  126. checksum(sum, line)
  127.     register int sum;
  128.     register char *line;
  129. {
  130.     while (*line++) {
  131.     if (sum & 1)
  132.         sum = (sum >> 1) + 0x8000;
  133.     else
  134.         sum >>= 1;
  135.  
  136.     sum = (sum + *line) & 0xFFFF;
  137.     }
  138.     return sum;
  139. }
  140.  
  141. int 
  142. runc(argv, errname)
  143.     char **argv;
  144.     char *errname;
  145. {
  146.     int status;
  147.  
  148.     switch (pid = fork()) {
  149.     case 0:            /* child */
  150.     (void) freopen(errname, "w", stderr);
  151.     execvp(compiler, argv);
  152.     perror("Couldn't exec compiler");
  153.     exit (1);
  154.  
  155.     case -1:            /* Error */
  156.     perror("Couldn't fork compiler");
  157.     exit (1);
  158.  
  159.     default:            /* Parent */
  160.     while (wait(&status) != pid);    /* wait for compile to finish */
  161.     break;
  162.     }
  163.     return ((status >> 8) & 0xFF);
  164. }
  165.  
  166. void 
  167. listerrs(errname)
  168.     char *errname;
  169. {
  170.     FILE *errfile;
  171.     char errline[BUFSIZ + 1];
  172.  
  173.     if ((errfile = fopen(errname, "r")) == NULL)
  174.     return;
  175.     while (fgets(errline, BUFSIZ, errfile) != NULL)
  176.     (void) fputs(errline, stderr);
  177.     (void) fclose(errfile);
  178.     (void) unlink(errname);
  179. }
  180.  
  181. void 
  182. edit(mergename)
  183.     char *mergename;
  184. {
  185.     int status;
  186.     char sfirsterr[6];
  187.  
  188.     switch (pid = fork()) {
  189.     case 0:            /* Child */
  190.     if (viedit) {
  191.         (void) sprintf(sfirsterr, "+%d", firsterr);
  192.         (void) printf(" vi %s %s\n", sfirsterr, mergename);
  193.         execlp(editor, "vi", sfirsterr, mergename, NULL);
  194.     } else {
  195.         (void) printf(" %s %s\n", edname, mergename);
  196.         execlp(editor, edname, mergename, NULL);
  197.     }
  198.     perror("Couldn't exec editor");
  199.     listerrs(errname);
  200.     exit (1);
  201.  
  202.     case -1:            /* Error */
  203.     perror("Couldn't fork editor");
  204.     listerrs(errname);
  205.     exit (1);
  206.  
  207.     default:            /* Parent */
  208.     while (wait(&status) != pid);    /* wait for editor to finish */
  209.     break;
  210.     }
  211. }
  212.  
  213. int 
  214. errinfo(errfile, srcname, errmsg)
  215.     FILE *errfile;
  216.     char *srcname, *errmsg;
  217. {
  218.     static char errline[BUFSIZ + 1];
  219.     char slineno[8];
  220.     char *p1;
  221.  
  222.     for (;;) {
  223.     /*    get next line from error message file    */
  224.     if (fgets(errline, BUFSIZ, errfile) == NULL)
  225.         return 0;
  226.  
  227.     errline[strlen(errline) - 1] = '\0';    /* trim newline */
  228.     p1 = errline;
  229.  
  230.     /*    does it match the pattern?    */
  231.     if (re_exec(p1, errdfa)) {
  232.         sprintf(srcname, "%.*s", braelist[filevar] - braslist[filevar],
  233.                         braslist[filevar]);
  234.         sprintf(slineno, "%.*s", braelist[linevar] - braslist[linevar],
  235.                         braslist[linevar]);
  236.         sprintf(errmsg, "%.*s", braelist[msgvar] - braslist[msgvar],
  237.                         braslist[msgvar]);
  238.         return atoi(slineno);
  239.         }
  240.     }
  241. }
  242.  
  243. char *merge(errname, mergename)
  244.     char *errname, *mergename;
  245. {
  246.     FILE *errfile, *srcfile, *mergefile;
  247.     int eof = 0, slineno, elineno, elines;
  248.     static char firstname[128];
  249.     char srcline[BUFSIZ + 1];
  250.     char srcname[128], errmsg[80];
  251.  
  252.     if ((errfile = fopen(errname, "r")) == NULL) {
  253.     perror(errname);
  254.     exit (1);
  255.     }
  256.     if ((firsterr = errinfo(errfile, srcname, errmsg)) == 0)
  257.     return NULL;
  258.  
  259.     if (access(srcname, 2) < 0)    /* writeable ? */
  260.     return NULL;
  261.  
  262.     if ((srcfile = fopen(srcname, "r")) == NULL) {
  263.     perror(srcname);
  264.     exit (1);
  265.     }
  266.     if (*mergename == '\0') {
  267.     char *p = strrchr(srcname, '/');
  268.     if (p == NULL)
  269.         p = srcname;
  270.     else
  271.         p++;
  272.     (void) sprintf(mergename, "/tmp/%d.%s", getpid(), p);
  273.     }
  274.     if ((mergefile = fopen(mergename, "w")) == NULL) {
  275.     perror(mergename);
  276.     exit (1);
  277.     }
  278.     slineno = 0;
  279.     elineno = firsterr;
  280.     elines = 0;
  281.     (void) strcpy(firstname, srcname);
  282.     chksum1 = 0;
  283.  
  284.     if (!viedit) {
  285.         (void) fprintf(mergefile, ">>>><<<< (%d)\n", firsterr + 1);
  286.         elines++;
  287.     }
  288.     while (!eof) {
  289.     if (!(eof = (fgets(srcline, BUFSIZ, srcfile) == NULL))) {
  290.         chksum1 = checksum(chksum1, srcline);
  291.         (void) fputs(srcline, mergefile);
  292.     }
  293.     slineno++;
  294.     while (slineno == elineno) {
  295.         elines++;
  296.         (void) fprintf(mergefile, ">>>> %s <<<<", errmsg);
  297.         if ((elineno = errinfo(errfile, srcname, errmsg)) == 0
  298.         || strcmp(firstname, srcname) != 0)
  299.         (void) fprintf(mergefile, " (last error)\n");
  300.         else
  301.         (void) fprintf(mergefile, " (%d)\n", elineno + elines);
  302.     }
  303.     }
  304.     (void) fclose(errfile);
  305.     (void) fclose(srcfile);
  306.     (void) fclose(mergefile);
  307.     return (firstname);
  308. }
  309.  
  310. /*
  311.  * Strip out merged error messages and compute checksum
  312.  */
  313. void 
  314. unmerge(mergename, srcname)
  315.     char *mergename, *srcname;
  316. {
  317.     FILE *mergefile, *srcfile;
  318.     char *p, srcline[BUFSIZ + 1];
  319.     struct stat merge, src;
  320.  
  321.     if (stat(mergename, &merge) != 0) {
  322.     perror(mergename);
  323.     exit(1);
  324.     }
  325.  
  326.     if (stat(srcname, &src) != 0) {
  327.     perror(srcname);
  328.     exit(1);
  329.     }
  330.  
  331.     if (merge.st_mtime < src.st_mtime) {    /* src is newer, don't */
  332.     return;                    /* crong it from tmp   */
  333.     }
  334.  
  335.     if ((mergefile = fopen(mergename, "r")) == NULL) {
  336.     perror(mergename);
  337.     exit (1);
  338.     }
  339.     if ((srcfile = fopen(srcname, "w")) == NULL) {
  340.     perror(srcname);
  341.     exit (1);
  342.     }
  343.     chksum2 = 0;
  344.     while (fgets(srcline, BUFSIZ, mergefile) != NULL) {
  345.     for (p = srcline; isspace(*p); p++);
  346.     if (strncmp(p, ">>>>", 4) != 0) {
  347.         chksum2 = checksum(chksum2, srcline);
  348.         (void) fputs(srcline, srcfile);
  349.     }
  350.     }
  351.  
  352.     (void) fclose(mergefile);
  353.     (void) fclose(srcfile);
  354. }
  355.  
  356. void 
  357. quit()
  358. {
  359.     (void) kill(pid, SIGTERM);
  360.     (void) unlink(errname);
  361.     (void) unlink(mergename);
  362.     exit (1);
  363. }
  364.  
  365. main(argc, argv)
  366.     int argc;
  367.     char *argv[];
  368. {
  369.     char    *p, *s, *d;
  370.     int i, status, nvars;
  371.  
  372.     if ((editor = getenv("EDITOR")) == NULL)
  373.     editor = "vi";
  374.     edname = (edname = strrchr(editor, '/')) == NULL ? editor : edname + 1;
  375.     viedit = strcmp(edname, "vi") == 0;
  376.  
  377.     if ((compiler = getenv("COMPILER")) == NULL)
  378.     compiler = "cc";
  379.     argv[0] = compiler;
  380.  
  381.     (void) mktemp(errname);
  382.  
  383.     signal(SIGINT, quit);
  384.     signal(SIGTERM, quit);
  385.     signal(SIGHUP, quit);
  386.  
  387.     if (p = getenv("ERRORPATTERN"))
  388.     strcpy(errpat, p);
  389.  
  390.     nvars = 0;
  391.  
  392.     /*  preprocess pattern to turn %f and %l into \(.*\) so that regex    */
  393.     /*  will remember the file and line numbers.                          */
  394.     for (s = errpat, d = errpato; *s;) {
  395.     if (*s == '%' && s[1] == 'f') {
  396.         *d++ = '\\'; *d++ = '('; *d++ = '.'; *d++ = '*';
  397.         *d++ = '\\'; *d++ = ')';
  398.         filevar = nvars++;
  399.         s += 2;
  400.         }
  401.     else if (*s == '%' && s[1] == 'm') {
  402.         *d++ = '\\'; *d++ = '('; *d++ = '.'; *d++ = '*';
  403.         *d++ = '\\'; *d++ = ')';
  404.         msgvar = nvars++;
  405.         s += 2;
  406.         }
  407.     else if (*s == '%' && s[1] == 'l') {
  408.         *d++ = '\\'; *d++ = '(';
  409.         *d++ = '['; *d++ = '0'; *d++ = '-'; *d++ = '9'; *d++ = ']';
  410.         *d++ = '*';
  411.         *d++ = '\\'; *d++ = ')';
  412.         s += 2;
  413.         linevar = nvars++;
  414.         }
  415.     else *d++ = *s++;
  416.     }
  417.  
  418.     errdfa = re_comp(errpato);
  419.  
  420.     while (status = runc(argv, errname)) {
  421.     if ((srcname = merge(errname, mergename)) == NULL) {
  422.         listerrs(errname);
  423.         exit (status);    /* couldn't merge */
  424.     }
  425.     edit(mergename);
  426.     (void) unlink(errname);
  427.  
  428.     signal(SIGINT,  SIG_IGN);
  429.     signal(SIGTERM, SIG_IGN);
  430.     signal(SIGHUP,  SIG_IGN);
  431.  
  432.     unmerge(mergename, srcname);
  433.     (void) unlink(mergename);
  434.  
  435.     signal(SIGINT,  quit);
  436.     signal(SIGTERM, quit);
  437.     signal(SIGHUP,  quit);
  438.  
  439.     if (chksum1 == chksum2)    /* file unchanged ? */
  440.         break;
  441.  
  442.     putchar(' ');
  443.     for (i = 0; i < argc; i++)
  444.         (void) printf("%s ", argv[i]);
  445.     putchar('\n');
  446.     }
  447.     listerrs(errname);
  448.     (void) unlink(errname);
  449.     exit (status);
  450. }
  451.  
  452. char *alloc(siz)
  453.     {
  454.     char *calloc();
  455.     char *r;
  456.     r = calloc(1, siz);
  457.     if (!r)
  458.         {
  459.         fprintf(stderr, "no memory\n");
  460.         exit(0);
  461.         }
  462.     return r;
  463.     }
  464. AlBeRtEiNsTeIn
  465. echo unbundling regex.c 1>&2
  466. cat >regex.c <<'AlBeRtEiNsTeIn'
  467. /* @(#)regex.c  4.1 (Berkeley) 12/21/80 */
  468. #
  469.  
  470. /*
  471.  * routines to do regular expression matching
  472.  *
  473.  * Entry points:
  474.  *
  475.  *      re_comp(s)
  476.  *              char *s;
  477.  *       ... returns 0 if the string s was compiled successfully,
  478.  *                   a pointer to an error message otherwise.
  479.  *           If passed 0 or a null string returns without changing
  480.  *           the currently compiled re (see note 11 below).
  481.  *
  482.  *      re_exec(s)
  483.  *              char *s;
  484.  *       ... returns 1 if the string s matches the last compiled regular
  485.  *                     expression, 
  486.  *                   0 if the string s failed to match the last compiled
  487.  *                     regular expression, and
  488.  *                  -1 if the compiled regular expression was invalid 
  489.  *                     (indicating an internal error).
  490.  *
  491.  * The strings passed to both re_comp and re_exec may have trailing or
  492.  * embedded newline characters; they are terminated by nulls.
  493.  *
  494.  * The identity of the author of these routines is lost in antiquity;
  495.  * this is essentially the same as the re code in the original V6 ed.
  496.  *
  497.  * The regular expressions recognized are described below. This description
  498.  * is essentially the same as that for ed.
  499.  *
  500.  *      A regular expression specifies a set of strings of characters.
  501.  *      A member of this set of strings is said to be matched by
  502.  *      the regular expression.  In the following specification for
  503.  *      regular expressions the word `character' means any character but NUL.
  504.  *
  505.  *      1.  Any character except a special character matches itself.
  506.  *          Special characters are the regular expression delimiter plus
  507.  *          \ [ . and sometimes ^ * $.
  508.  *      2.  A . matches any character.
  509.  *      3.  A \ followed by any character except a digit or ( )
  510.  *          matches that character.
  511.  *      4.  A nonempty string s bracketed [s] (or [^s]) matches any
  512.  *          character in (or not in) s. In s, \ has no special meaning,
  513.  *          and ] may only appear as the first letter. A substring 
  514.  *          a-b, with a and b in ascending ASCII order, stands for
  515.  *          the inclusive range of ASCII characters.
  516.  *      5.  A regular expression of form 1-4 followed by * matches a
  517.  *          sequence of 0 or more matches of the regular expression.
  518.  *      6.  A regular expression, x, of form 1-8, bracketed \(x\)
  519.  *          matches what x matches.
  520.  *      7.  A \ followed by a digit n matches a copy of the string that the
  521.  *          bracketed regular expression beginning with the nth \( matched.
  522.  *      8.  A regular expression of form 1-8, x, followed by a regular
  523.  *          expression of form 1-7, y matches a match for x followed by
  524.  *          a match for y, with the x match being as long as possible
  525.  *          while still permitting a y match.
  526.  *      9.  A regular expression of form 1-8 preceded by ^ (or followed
  527.  *          by $), is constrained to matches that begin at the left
  528.  *          (or end at the right) end of a line.
  529.  *      10. A regular expression of form 1-9 picks out the longest among
  530.  *          the leftmost matches in a line.
  531.  *      11. An empty regular expression stands for a copy of the last
  532.  *          regular expression encountered.
  533.  */
  534.  
  535. /*
  536.  * constants for re's
  537.  */
  538. #define CBRA    1
  539. #define CCHR    2
  540. #define CDOT    4
  541. #define CCL     6
  542. #define NCCL    8
  543. #define CEOF    11
  544. #define CKET    12
  545. #define CBACK   18
  546.  
  547. #define CSTAR   01
  548.  
  549. #define ESIZE   512
  550. #define NBRA    9
  551.  
  552. static char *names[] = { "?", "\\(", "char", "char*", ".",
  553.                 ".*", "[", "[*", "[^", "[^*",
  554.                 "?", "$", "\\)", "?", "?", "?", "?", "?", "\\" };
  555.  
  556. char    expbuf[ESIZE], *braslist[NBRA], *braelist[NBRA];
  557. static  char    circf = 1;
  558.  
  559. /*
  560.  * compile the regular expression argument into a dfa
  561.  */
  562. char *
  563. re_comp(sp)
  564.         register char   *sp;
  565. {
  566.     char *alloc();
  567.         register int    c;
  568.         register char   *ep = expbuf;
  569.         int     cclcnt, numbra = 0;
  570.         char    *lastep = 0;
  571.         char    bracket[NBRA];
  572.         char    *bracketp = &bracket[0];
  573.         static  char    *retoolong = "Regular expression too long";
  574.  
  575. #define comerr(msg) {expbuf[0] = 0; numbra = 0; printf(msg); return(0); }
  576.  
  577.         if (sp == 0 || *sp == '\0') {
  578.                 if (*ep == 0)
  579.                         comerr("No previous regular expression\n");
  580.                 return(0);
  581.         }
  582.         /*      if (*sp == '^') {
  583.          *        circf = 1;
  584.          *        sp++;
  585.          *         }
  586.          *    else circf = 0;
  587.      */
  588.         for (;;) {
  589.                 if (ep >= &expbuf[ESIZE])
  590.                         comerr(retoolong);
  591.                 if ((c = *sp++) == '\0') {
  592.                         if (bracketp != bracket)
  593.                                 comerr("unmatched \\(");
  594.                         *ep++ = CEOF;
  595.                         *ep++ = 0;
  596.             sp = alloc(ep - expbuf);
  597.             for (numbra = 0; numbra < ep - expbuf; numbra++)
  598.                 {
  599.                 sp[numbra] = expbuf[numbra];
  600.                 }
  601.             return sp;
  602.             }
  603.                 if (c != '*')
  604.                         lastep = ep;
  605.                 switch (c) {
  606.  
  607.                 case '.':
  608.                         *ep++ = CDOT;
  609.                         continue;
  610.  
  611.                 case '*':
  612.                         if (lastep == 0 || *lastep == CBRA || *lastep == CKET)
  613.                                 goto defchar;
  614.                         *lastep |= CSTAR;
  615.                         continue;
  616.  
  617.                 case '[':
  618.                         *ep++ = CCL;
  619.                         *ep++ = 0;
  620.                         cclcnt = 1;
  621.                         if ((c = *sp++) == '^') {
  622.                                 c = *sp++;
  623.                                 ep[-2] = NCCL;
  624.                         }
  625.                         do {
  626.                                 if (c == '\0')
  627.                                         comerr("missing ]");
  628.                                 if (c == '-' && ep [-1] != 0) {
  629.                                         if ((c = *sp++) == ']') {
  630.                                                 *ep++ = '-';
  631.                                                 cclcnt++;
  632.                                                 break;
  633.                                         }
  634.                                         while (ep[-1] < c) {
  635.                                                 *ep = ep[-1] + 1;
  636.                                                 ep++;
  637.                                                 cclcnt++;
  638.                                                 if (ep >= &expbuf[ESIZE])
  639.                                                         comerr(retoolong);
  640.                                         }
  641.                                 }
  642.                                 *ep++ = c;
  643.                                 cclcnt++;
  644.                                 if (ep >= &expbuf[ESIZE])
  645.                                         comerr(retoolong);
  646.                         } while ((c = *sp++) != ']');
  647.                         lastep[1] = cclcnt;
  648.                         continue;
  649.  
  650.                 case '\\':
  651.                         if ((c = *sp++) == '(') {
  652.                                 if (numbra >= NBRA)
  653.                                         comerr("too many \\(\\) pairs");
  654.                                 *bracketp++ = numbra;
  655.                                 *ep++ = CBRA;
  656.                                 *ep++ = numbra;
  657.                 numbra++;
  658.                                 continue;
  659.                         }
  660.                         if (c == ')') {
  661.                                 if (bracketp <= bracket)
  662.                                         comerr("unmatched \\)");
  663.                                 *ep++ = CKET;
  664.                                 *ep++ = *--bracketp;
  665.                                 continue;
  666.                         }
  667.                         if (c >= '1' && c < ('1' + NBRA)) {
  668.                                 *ep++ = CBACK;
  669.                                 *ep++ = c - '1';
  670.                                 continue;
  671.                         }
  672.                         *ep++ = CCHR;
  673.                         *ep++ = c;
  674.                         continue;
  675.  
  676.                 defchar:
  677.                 default:
  678.                         *ep++ = CCHR;
  679.                         *ep++ = c;
  680.                 }
  681.         }
  682. }
  683.  
  684.  
  685. /* 
  686.  * match the argument string against the compiled re
  687.  */
  688. int
  689. re_exec(subject, pattern, fromline)
  690.         register char   *subject;
  691.         register char   *pattern;
  692. {
  693.         register int    c;
  694.         int     rv;
  695.  
  696.         for (c = 0; c < NBRA; c++) {
  697.                 braslist[c] = 0;
  698.                 braelist[c] = 0;
  699.         }
  700.         if (circf) {
  701.                 c = (advance(subject, pattern));
  702.         /* printf("return %d from %d\n", c, fromline); */
  703.         return c;
  704.         }
  705.         /*
  706.          * fast check for first character
  707.          */
  708.         if (*pattern == CCHR) {
  709.                 c = pattern[1];
  710.                 do {
  711.                         if (*subject != c)
  712.                                 continue;
  713.                         if (rv = advance(subject, pattern)) {
  714.                 /* printf("return %d from %d\n", rv, fromline); */
  715.                                 return(rv);
  716.                 }
  717.                 } while (*subject++);
  718.         /* printf("return 0 from %d\n", fromline); */
  719.                 return(0);
  720.         }
  721.         /*
  722.          * regular algorithm
  723.          */
  724.         do
  725.                 if (rv = advance(subject, pattern)) {
  726.             /* printf("return %d from %d\n", rv, fromline); */
  727.                         return(rv);
  728.             }
  729.         while (*subject++);
  730.     /* printf("return 0 from %d\n", fromline); */
  731.         return(0);
  732. }
  733.  
  734. /* 
  735.  * try to match the next thing in the dfa
  736.  */
  737. static  int
  738. advance(lp, ep)
  739.         register char   *lp, *ep;
  740. {
  741.         register char   *curlp;
  742.         int     ct, i;
  743.         int     rv;
  744.  
  745.         for (;;)
  746.                 switch (*ep++) {
  747.  
  748.                 case CCHR:
  749.                         if (*ep++ == *lp++)
  750.                                 continue;
  751.                         return(0);
  752.  
  753.                 case CDOT:
  754.                         if (*lp++)
  755.                                 continue;
  756.                         return(0);
  757.  
  758.                 case CEOF:
  759.                         if (*lp == 0) return(1);
  760.                         return(0);
  761.  
  762.                 case CCL:
  763.                         if (cclass(ep, *lp++, 1)) {
  764.                                 ep += *ep;
  765.                                 continue;
  766.                         }
  767.                         return(0);
  768.  
  769.                 case NCCL:
  770.                         if (cclass(ep, *lp++, 0)) {
  771.                                 ep += *ep;
  772.                                 continue;
  773.                         }
  774.                         return(0);
  775.  
  776.                 case CBRA:
  777.                         braslist[*ep++] = lp;
  778.                         continue;
  779.  
  780.                 case CKET:
  781.                         braelist[*ep++] = lp;
  782.                         continue;
  783.  
  784.                 case CBACK:
  785.                         if (braelist[i = *ep++] == 0)
  786.                                 return(-1);
  787.                         if (backref(i, lp)) {
  788.                                 lp += braelist[i] - braslist[i];
  789.                                 continue;
  790.                         }
  791.                         return(0);
  792.  
  793.                 case CBACK|CSTAR:
  794.                         if (braelist[i = *ep++] == 0)
  795.                                 return(-1);
  796.                         curlp = lp;
  797.                         ct = braelist[i] - braslist[i];
  798.                         while (backref(i, lp))
  799.                                 lp += ct;
  800.                         while (lp >= curlp) {
  801.                                 if (rv = advance(lp, ep))
  802.                                         return(rv);
  803.                                 lp -= ct;
  804.                         }
  805.                         continue;
  806.  
  807.                 case CDOT|CSTAR:
  808.                         curlp = lp;
  809.                         while (*lp++)
  810.                                 ;
  811.                         goto star;
  812.  
  813.                 case CCHR|CSTAR:
  814.                         curlp = lp;
  815.                         while (*lp++ == *ep)
  816.                                 ;
  817.                         ep++;
  818.                         goto star;
  819.  
  820.                 case CCL|CSTAR:
  821.                 case NCCL|CSTAR:
  822.                         curlp = lp;
  823.                         while (cclass(ep, *lp++, ep[-1] == (CCL|CSTAR)))
  824.                                 ;
  825.                         ep += *ep;
  826.                         goto star;
  827.  
  828.                 star:
  829.                         do {
  830.                                 lp--;
  831.                                 if (rv = advance(lp, ep))
  832.                                         return(rv);
  833.                         } while (lp > curlp);
  834.                         return(0);
  835.  
  836.                 default:
  837.             printf("oops %d\n", *(ep - 1));
  838.                         return(-1);
  839.                 }
  840. }
  841.  
  842. backref(i, lp)
  843.         register int    i;
  844.         register char   *lp;
  845. {
  846.         register char   *bp;
  847.  
  848.         bp = braslist[i];
  849.         while (*bp++ == *lp++)
  850.                 if (bp >= braelist[i])
  851.                         return(1);
  852.         return(0);
  853. }
  854.  
  855. int
  856. cclass(set, c, af)
  857.         register char   *set, c;
  858.         int     af;
  859. {
  860.         register int    n;
  861.  
  862.         if (c == 0)
  863.                 return(0);
  864.         n = *set++;
  865.         while (--n)
  866.                 if (*set++ == c)
  867.                         return(af);
  868.         return(! af);
  869. }
  870. AlBeRtEiNsTeIn
  871.